/**
 * Created by Edik on 2017/4/27.
 */
(function(){

    var datepicker = function(conf){

        var monthData;
        var $wrapper;
        var Dates = {};
        var EDATEID;
        var configs = {
            el: '',
            showWeek: false
        };

        //生成唯一ID
        EDATEID = 'EDATEID-' + new Date().getTime();

        configs.el = conf.el;
        configs.showWeek = conf.showWeek || false;

        var input = configs.el;
        var $input;
        if("." == input.substr(0,1)){
            $input = document.querySelector(input);
        }else if ("#" == input.substr(0,1)){
            $input = document.getElementById(input.substr(1));
        }else {
            throw new Error('元素选择器错误，class请用"."，ID请用"#"！');
        }

        Dates.init = function () {

            Dates.render({});

            //给input绑定事件
            AddEvent($input, 'click',function(){
                if(Dates.hasClass($wrapper, 'ui-datepicker-wrapper-show')){
                    Dates.removeClass($wrapper, 'ui-datepicker-wrapper-show')
                }else{
                    Dates.addClass($wrapper, 'ui-datepicker-wrapper-show');
                    var left = $input.offsetLeft;
                    var top = $input.offsetTop;
                    var height = $input.offsetHeight;

                    $wrapper.style.top = top + height + 2 + 'px';
                    $wrapper.style.left = left + 'px';
                }
            })

            AddEvent($wrapper, 'click', function (e) {
                var e = e || event;
                //获得触发事件的元素
                var $target = e.srcElement ? e.srcElement:e.target;

                //日期单元格选定事件
                if(Dates.hasClass($target, 'edik-datepicker-day')){
                    var date = new Date(monthData.year, monthData.month - 1, $target.dataset ? $target.dataset.date:$target.getAttribute('data-date'));

                    $input.value = format(date);
                    Dates.removeClass($wrapper, 'ui-datepicker-wrapper-show');
                    Dates.render({year: date.getFullYear(), month: date.getMonth() + 1, day: date.getDate()});
                }

                //月份切换事件
                if(Dates.hasClass($target, 'edik-datepicker-prev-month')){
                    //上一月
                    Dates.render({derection:'prev_month'});
                }else if(Dates.hasClass($target, 'edik-datepicker-next-month')){
                    //下一月
                    Dates.render({derection:'next_month'});
                }else if (Dates.hasClass($target, 'datepicker-js-m')){
                    //显示隐藏月份选择
                    var $ms = document.getElementById((EDATEID + '_ms'));
                    if(Dates.hasClass($ms, 'ui-datepicker-wrapper-show')){
                        Dates.removeClass($ms, 'ui-datepicker-wrapper-show')
                    }else{
                        Dates.addClass($ms, 'ui-datepicker-wrapper-show')
                    }
                }else if(Dates.hasClass($target, 'datepicker-js-ms')){
                    //月份选择点击事件
                    var myear = document.getElementById(EDATEID+'_input__year').value;
                    Dates.render({year: myear.substr(0,myear.length - 1), month: $target.getAttribute('data-m')});
                }

                //年份切换事件
                if(Dates.hasClass($target, 'edik-datepicker-prev-year')){
                    //上一年
                    Dates.render({derection:'prev_year'});
                }else if(Dates.hasClass($target, 'edik-datepicker-next-year')){
                    //下一年
                    Dates.render({derection:'next_year'});
                }else if(Dates.hasClass($target, 'datepicker-js-y')){
                    //显示隐藏年份选择
                    var $ms = document.getElementById((EDATEID + '_ys'));
                    if(Dates.hasClass($ms, 'ui-datepicker-wrapper-show')){
                        Dates.removeClass($ms, 'ui-datepicker-wrapper-show')
                    }else{
                        Dates.addClass($ms, 'ui-datepicker-wrapper-show')
                    }
                }else if(Dates.hasClass($target, 'datepicker-js-ys')){
                    //年份点击事件
                    var ymonth = document.getElementById(EDATEID+'_input__month').value;
                    Dates.render({year: $target.getAttribute('data-y'), month: ymonth.substr(0, ymonth.length - 1)});
                }else if (Dates.hasClass($target, 'ui-datepicker_chtop_btn')){
                    //年份选择向上翻页
                    var $firstLi = document.getElementById(EDATEID+'_year_firstli');
                    document.getElementById(EDATEID+'_year_ul').innerHTML = Dates.createYear(Number($firstLi.getAttribute('data-y')) - 7)
                }else if (Dates.hasClass($target, 'ui-datepicker_chdown_btn')){
                    //年份选择向下翻页
                    var $lastLi = document.getElementById(EDATEID+'_year_lastli');
                    document.getElementById(EDATEID+'_year_ul').innerHTML = Dates.createYear(Number($lastLi.getAttribute('data-y')) + 6)
                }

            });
        }

        Dates.createYear = function(year){
            var htmlYear = Number(year);
            var html = '';
            for(var i=(htmlYear - 5);i<htmlYear;i++){
                if (i == (htmlYear - 5)){
                    html += '  <li data-y="'+i+'" class="datepicker-js-ys" id="'+EDATEID+'_year_firstli">'+i+'年</li>                                        ';
                }else {
                    html += '  <li data-y="'+i+'" class="datepicker-js-ys">'+i+'年</li>                                        ';
                }
            }
            for(var i=htmlYear;i<(htmlYear + 7);i++){
                if(i == (htmlYear + 6)){
                    html += '  <li data-y="'+i+'" class="datepicker-js-ys" id="'+EDATEID+'_year_lastli">'+i+'年</li>                                        ';
                }else {
                    html += '  <li data-y="'+i+'" class="datepicker-js-ys">'+i+'年</li>                                        ';
                }
            }

            return html;
        }

        //生成HTML
        Dates.buildUi = function(year, month, day){
            monthData = Dates.getMonthDate(year, month, day);

            var htmlYear = Number(monthData.year);

            var html =
                '<div class="ui-datepicker-header">                                                              '+
                '    <div class="ui-datepicker_ym ui-datepicker_y" id="ui-datepicker_YY">                        '+
                '        <a class="ui-datepicker_choose ui-datepicker_chprev edik-datepicker-prev-year"><cite class="edik-datepicker-prev-year"></cite></a>                 '+
                '        <input id="'+EDATEID+'_input__year" class="datepicker-js-y" readonly="" value="'+monthData.year+'年">                                 '+
                '        <label class="datepicker-js-y"></label>                                                                         '+
                '        <a class="ui-datepicker_choose ui-datepicker_chnext edik-datepicker-next-year"><cite class="edik-datepicker-next-year"></cite></a>                 '+
                '        <div id="'+EDATEID+'_ys" class="ui-datepicker_ys ">                                         '+
                '            <a class="ui-datepicker_tab ui-datepicker_chtop ui-datepicker_chtop_btn" ><cite class="ui-datepicker_chtop_btn"></cite></a>  '+
                '            <ul id="'+EDATEID+'_year_ul" class="'+EDATEID+'_year_ul">                                          ';

            //年份
            html += Dates.createYear(htmlYear);

            html +=
                '            </ul>                                                               '+
                '            <a class="ui-datepicker_tab ui-datepicker_chdown ui-datepicker_chdown_btn" ><cite class="ui-datepicker_chdown_btn"></cite></a> '+
                '        </div>                                                                  '+
                '    </div>                                                                                      '+
                '    <div class="ui-datepicker_ym ui-datepicker_m" id="ui-datepicker_MM">                        '+
                '        <a class="ui-datepicker_choose ui-datepicker_chprev edik-datepicker-prev-month"><cite class="edik-datepicker-prev-month"></cite></a>'+
                '        <input id="'+EDATEID+'_input__month" class="datepicker-js-m" readonly="" value="'+(Number(monthData.month) < 10?'0'+Number(monthData.month):monthData.month)+'月">                                   '+
                '        <label class="datepicker-js-m"></label>                                                                         '+
                '        <a class="ui-datepicker_choose ui-datepicker_chnext edik-datepicker-next-month"><cite class="edik-datepicker-next-month"></cite></a>'+
                '        <div id="'+EDATEID+'_ms" class="ui-datepicker_ms ">             ';

            //12月份
            for(var i=1;i<13;i++){
                html += '<span data-m="'+i+'" class="datepicker-js-ms">'+(i<10? '0'+i:i)+'月</span>        ';
            }

            html +=
                '        </div>                                                          '+
                '    </div>                                                              '+
                '</div>                                                                  '+
                '<div class="ui-datepicker-body">                                        '+
                '    <table>                                                             '+
                '        <thead>                                                         '+
                '            <tr>                                                        ';
            if(configs.showWeek){
                html += '        <th>周</th>                                             ';
            }
            html +=
                '                <th>一</th>                                             '+
                '                <th>二</th>                                             '+
                '                <th>三</th>                                             '+
                '                <th>四</th>                                             '+
                '                <th>五</th>                                             '+
                '                <th>六</th>                                             '+
                '                <th>日</th>                                             '+
                '            </tr>                                                       '+
                '        </thead>                                                        '+
                '        <tbody>                                                         ';

            for(var i=0;i<monthData.days.length;i++){
                var date = monthData.days[i];

                var weekDay = 7;
                if(configs.showWeek){
                    weekDay = 8
                }

                if(i%weekDay === 0){
                    html += '<tr>';
                }
                var tdClass = date.type == "week" ? "edik-datepicker-week" : ((date.date < 1 || date.date > date.lastDay) ? 'edik-datepicker-other-day edik-datepicker-day' : 'edik-datepicker-day');

                var theDayClass = date.theDay ? 'edik-datepicker-this-day':'';

                html += '<td data-date="'+ date.date +'" class="'+ tdClass + ' ' + theDayClass +'" >' + date.showDate + '</td>';
                if(i%weekDay === (weekDay - 1)){
                    html += '</tr>';
                }
            }

            html +=
                '        </tbody>                                                        '+
                '    </table>                                                            '+
                '</div>                                                                  ';

            return html;

        }

        //把数据加载到页面
        Dates.render = function(conf){
            var year,month,day;
            if(monthData){
                year = monthData.year;
                month = monthData.month;
            }

            if(conf.year) year = conf.year;
            if(conf.month) month = conf.month;
            if(conf.day) day = conf.day;

            if(conf.derection === 'prev_month') month--;
            if(conf.derection === 'next_month') month++;
            if(conf.derection === 'prev_year') year--;
            if(conf.derection === 'next_year') year++;

            if(month === 0){
                year--;
                month = 12
            }else if(month === 13){
                year++;
                month = 1;
            }

            var html = Dates.buildUi(year, month, day);

            if(!$wrapper){
                $wrapper = document.createElement('div');
                document.body.appendChild($wrapper);
                $wrapper.className = 'ui-datepicker-wrapper';
                $wrapper.id = EDATEID;
            }
            $wrapper.innerHTML = html;
        }

        //获取月份的天数信息
        Dates.getMonthDate = function (year, month, day) {

            var ret = [];
            //如果年份或者月份为空
            if(!year || !month){
                var today = new Date();
                year = today.getFullYear();
                month = today.getMonth() + 1;
                day = today.getDate();
            }

            //获取当前月份第一天
            var firstDay = new Date(year, month - 1, 1);
            //获取当前月份第一天的星期
            var firstDayWeekDay = firstDay.getDay();
            //周日
            if(firstDayWeekDay === 0){
                firstDayWeekDay = 7;
            }

            //获取上个月最后一天
            var lastDayOfLastMonth = new Date(year, month - 1, 0);
            var lastDateOfLastMonth = lastDayOfLastMonth.getDate();

            //上个月需要显示的天数
            var preMonthDayCount = firstDayWeekDay - 1;

            //本月的最后一天
            var lastDay = new Date(year, month, 0);
            var lastDate = lastDay.getDate();

            for(var i=0;i<7*6;i++){
                var date = i + 1 - preMonthDayCount;
                var showDate = date;
                var thisMonth = month;

                if(date <= 0){
                    //上个月
                    thisMonth = month - 1;
                    showDate = lastDateOfLastMonth + date;
                }else if(date > lastDate){
                    //下个月
                    thisMonth = month + 1;
                    showDate = showDate - lastDate;
                }

                if(thisMonth === 0) thisMonth = 12;
                if(thisMonth === 13) thisMonth = 1;

                var week = 0;
                if(configs.showWeek && i%7 == 0){
                    if(i==0 && month == '1'){
                        ret.push({
                            type: 'week',
                            month: thisMonth,
                            date: date,
                            showDate: 1,
                            lastDay: lastDate,
                            theDay: false
                        })
                    }else{
                        ret.push({
                            type: 'week',
                            month: thisMonth,
                            date: date,
                            showDate: Dates.getWeekNumber(year,month,date),
                            lastDay: lastDate,
                            theDay: false
                        })
                    }

                }

                ret.push({
                    type: 'day',
                    month: thisMonth,
                    date: date,
                    showDate: showDate,
                    lastDay: lastDate,
                    theDay: (date == day)
                })
            }

            return {
                year: year,
                month: month,
                days: ret
            };

        }

        // 判断是否包含某个class
        Dates.hasClass = function(elem, cls){
            elem = elem || {};
            return new RegExp('\\b' + cls +'\\b').test(elem.className);
        };

        //添加class
        Dates.addClass = function(elem, cls){
            elem = elem || {};
            Dates.hasClass(elem, cls) || (elem.className += ' ' + cls);
            elem.className = Dates.trim(elem.className);
            return this;
        };

        //删除class
        Dates.removeClass = function(elem, cls) {
            elem = elem || {};
            if (Dates.hasClass(elem, cls)) {
                var reg = new RegExp('\\b' + cls +'\\b');
                elem.className = elem.className.replace(reg, '');
            }
            return this;
        };
        Dates.trim = function(str){
            str = str || '';
            return str.replace(/^\s|\s$/g, '').replace(/\s+/g, ' ');
        };
        //判断闰年
        Dates.isleap = function(year){
            return (year%4 === 0 && year%100 !== 0) || year%400 === 0;
        };
        //获取某一年份的某一月份的天数
        Dates.getMonthDays = function(year, month) {
            return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month] || (Dates.isleap(year) ? 29 : 28);
        }

        //获取某年的某天是第几周
        Dates.getWeekNumber = function(y, m, d) {
            var now = new Date(y, m - 1, d),
                year = now.getFullYear(),
                month = now.getMonth(),
                days = now.getDate();
            //那一天是那一年中的第多少天
            for (var i = 0; i < month; i++) {
                days += Dates.getMonthDays(year, i);
            }
            //那一年第一天是星期几
            var yearFirstDay = new Date(year, 0, 1).getDay() || 7;
            var week = null;
            if (yearFirstDay == 1) {
                week = Math.ceil(days / 7);
            } else {
                days -= (7 - yearFirstDay + 1);
                week = Math.ceil(days / 7) + 1;
            }
            return week;
        }


        Dates.init();

    }

    /**
     * 格式化日期
     * @param date 日期类型
     * @returns 返回 2017-05-01
     */
    function format(date){
        ret = '';
        var padding = function(num){
            return num < 10 ? '0'+num:num;
        }
        ret += date.getFullYear() + '-';
        ret += padding(date.getMonth() + 1) + '-';
        ret += padding(date.getDate());
        return ret;
    }

    /**
     * 监听事件兼容
     * @param elem 要绑定事件的元素
     * @param even 要绑定的事件
     * @param fn 绑定事件的函数
     */
    function AddEvent(elem, even, fn){
        elem.attachEvent ? elem.attachEvent('on'+ even, fn) : elem.addEventListener(even, fn, false);
    };

    window.datepicker = datepicker;
})();